package net.soe;

import net.soe.__Shape._;

object __Region {
abstract class _Region  {
	def Intersect(r: _Region) : _Region = {
			new Intersect(this, r)
	}

	def Union(r: _Region) : _Region = {
			new Union(this, r)
	}
	def Xor(r: _Region) : _Region = {
			new Xor(this, r)
	}
	
	//NOTE: To use the function as infix operator, xUnion is implemented in _Region class (in SOE this is in Picture)
	//> xUnion :: Region -> Region -> Region
	//> p1 `xUnion` p2 = (p1 `Intersect` Complement p2) `Union`
	//>                  (p2 `Intersect` Complement p1)
	def xUnion(r: _Region) : _Region = {
		(this Intersect  (Complement(r))) Union (r Intersect (Complement(this)))
	}
}
case class Shape( a: _Shape) extends _Region
case class Translate(a: Vector, b:_Region) extends _Region
case class Scale(a: Vector, b:_Region) extends _Region
case class Complement(a: _Region) extends _Region
case class Union(a:_Region, b:_Region) extends _Region
case class Intersect(a: _Region, b:_Region) extends _Region
case class Xor(a:_Region, b:_Region) extends _Region
case class Empty() extends _Region

type Vector = (Double, Double)
def oneCircle = Shape( Ellipse (1, 1))
// TODO:  instead of 100 make this to be infinite list of even numbers!
def manyCircles = for(x <- Stream.range(1, 100, 2)) yield Translate((x, 0), oneCircle)

// Kind of ugly to define Empty() as _Region.  Scala has problem with object types
// when they are used in the fold.  
// See: http://www.nabble.com/issues-with-foldLeft-td16645932.html
def fiveCircles = ((manyCircles take 5) foldRight (Empty():_Region)) {(a, b) => Union(a, b)}

}
